#include <iostream>
#include <fstream>
#include <algorithm>

#include <gtest/gtest.h>

#include "graph_data.h"
#include "graph_algo.h"
#include "graph.h"


struct DistanceTester : public testing::Test
{
  static graph_t * graph;    
protected:
  virtual void SetUp()
  {    
  }
  
  
  bool outputs_equal()
  {    
    return output.size() == reference_output.size() 
      && std::equal(output.begin(), output.end(), reference_output.begin());
  }

  std::vector<vertex_t> output;
  std::vector<vertex_t> reference_output;  
};

graph_t * DistanceTester::graph = NULL;

TEST_F(DistanceTester, DijkstraPath1)
{
  vertex_t path[3] = 
    {graph->vertex_by_id(1), 
     graph->vertex_by_id(2), 
     graph->vertex_by_id(0)};
  reference_output.assign(path, path + sizeof(path));
  
  dijkstra(*graph, graph->vertex_by_id(0), graph->vertex_by_id(1), std::back_inserter(output));
  EXPECT_TRUE(outputs_equal());
}


void make_graph(std::string const & path)
{
  size_t const BUFFER_SIZE = 1024;
  size_t const VERTICES_BUFFERS_COUNT = 10;
  size_t const EDGES_BUFFERS_COUNT = 10;
  std::ofstream vertices_stream((path + "/vertices").c_str());
  std::ofstream edges_stream((path + "/vertices").c_str());
  
  char buf[1024] = {0};
  for (size_t i = 0; i != VERTICES_BUFFERS_COUNT; ++i)
  {
    vertices_stream.write(buf, BUFFER_SIZE);
  }  
  for (size_t i = 0; i != EDGES_BUFFERS_COUNT; ++i)
  {
    edges_stream.write(buf, BUFFER_SIZE);
  }
}

void prepare_graph(graph_t & graph)
{
  vertex_t vertices[5];
  
  for (size_t i = 0; i != 5; ++i)
  {
    vertices[i] = graph.add_vertex(vertex_data_t(0., 0.));
  }
        
  graph.add_edge(vertices[0], vertices[1], 4);
  graph.add_edge(vertices[0], vertices[2], 2);
  graph.add_edge(vertices[1], vertices[2], 3);
  graph.add_edge(vertices[1], vertices[3], 2);
  graph.add_edge(vertices[1], vertices[4], 3);
  graph.add_edge(vertices[2], vertices[1], 1);
  graph.add_edge(vertices[2], vertices[3], 4);
  graph.add_edge(vertices[2], vertices[4], 5);
  graph.add_edge(vertices[4], vertices[3], 1);
}

int main()
{
  const char * const GRAPH_PATH = "test-graph";
  
  make_graph(GRAPH_PATH);
  DistanceTester::graph = new graph_t(GRAPH_PATH);
  
  prepare_graph(*DistanceTester::graph);
  
  RUN_ALL
}